#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/soc_caps.h"
#include "esp_log.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"

// 全局常量, 字符串, 用于日志打印的标签
const static char *TAG = "ADC";

// 全局变量, 整数, ADC转换原始结果
static int adc_raw;
// 全局变量, 整数, ADC转换校准结果(mV)
static int voltage;

void app_main(void)
{
    // ADC初始化，获得ADC单次转换句柄
    adc_oneshot_unit_handle_t adc1_handle;
    adc_oneshot_unit_init_cfg_t init_config1 = {
        .unit_id = ADC_UNIT_1,
    };
    adc_oneshot_new_unit(&init_config1, &adc1_handle);

    // ADC配置，设置ADC单次转换模式的参数
    adc_oneshot_chan_cfg_t config = {
        .bitwidth = ADC_BITWIDTH_DEFAULT,
        .atten = ADC_ATTEN_DB_11,
    };
    adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_2, &config);

    // ADC校准初始化，创建ADC校准曲线拟合方案句柄
    adc_cali_handle_t adc1_cali_handle = NULL;
    adc_cali_curve_fitting_config_t cali_config = {
        .unit_id = ADC_UNIT_1,
        .chan = ADC_CHANNEL_2,
        .atten = ADC_ATTEN_DB_11,
        .bitwidth = ADC_BITWIDTH_DEFAULT,
    };
    esp_err_t ret = adc_cali_create_scheme_curve_fitting(&cali_config, &adc1_cali_handle);
    if (ret == ESP_OK) {
        ESP_LOGI(TAG, "Calibration Success");
    } else if (ret == ESP_ERR_NOT_SUPPORTED) {
        ESP_LOGW(TAG, "eFuse not burnt, skip software calibration");
    } else {
        ESP_LOGE(TAG, "Invalid arg or no memory");
    }

    while (1) {
        {
            // 方案一：先获取ADC转换原始结果，再转换成校准结果(mV)
            adc_oneshot_read(adc1_handle, ADC_CHANNEL_2, &adc_raw);
            adc_cali_raw_to_voltage(adc1_cali_handle, adc_raw, &voltage);
            ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d, Cali Voltage: %d mV", ADC_UNIT_1 + 1, ADC_CHANNEL_2, adc_raw, voltage);
        }
        {
            // 方案二：使用快捷函数, 相当于先adc_oneshot_read(), 再adc_cali_raw_to_voltage()
            adc_oneshot_get_calibrated_result(adc1_handle, adc1_cali_handle, ADC_CHANNEL_2, &adc_raw);
            ESP_LOGI(TAG, "ADC%d Channel[%d] Cali Voltage: %d mV", ADC_UNIT_1 + 1, ADC_CHANNEL_2, voltage);
        }
        // 延时1000ms
        vTaskDelay(pdMS_TO_TICKS(1000));
    }

    // 删除ADC单次转换的句柄
    adc_oneshot_del_unit(adc1_handle);
    // 删除ADC校准曲线拟合方案句柄
    adc_cali_delete_scheme_curve_fitting(adc1_cali_handle);
}
